package main

/**
统计1-2000000的数字中的哪些是素数
传统方式，使用循环判断
优化方法，使用并发和并行的方式
“够浪” 将统计分配给多个goroutine去完成
*/

import (
	"fmt"
	"time"
)

var num3 int = 200000
var goNum3 int = 8
var intChanPut3 chan int = make(chan int, num3)

func main() {

	start := time.Now()

	var primeChan chan int = make(chan int, num3)
	var exitChan chan bool = make(chan bool, goNum3)
	go intChan3(num3)

	//isPrimes(200000)
	/**
	传统方式	20w 求素数耗时
	打印：52.8860728s	不打印：49.550748s
	*/

	/**
		go程x协程	20w 求素数耗时
	 	go程2协程	打印：19.7942222s	不打印：511.7µs
		go程4协程	打印：14.5736938s	不打印：230.5µs
		go程8协程	打印：12.5730693s	不打印：227.2µs
	*/

	for i := 0; i <= goNum3; i++ {
		go isPrimes3(intChanPut3, primeChan, exitChan)
	}

	go func() {
		for i := 0; i <= goNum3; i++ {
			<-exitChan
		}
		//close(primeChan)
	}()

label:
	for {
		select {
		case res := <-primeChan:
			fmt.Println("素数：", res)
		default:
			break label
		}

	}

	end := time.Since(start)
	fmt.Println(end)

}

// 填充0-num数据到管道
func intChan3(num int) {
	for i := 1; i <= num; i++ {
		intChanPut3 <- i
	}
	//close(intChanPut3)
}

/*
*
判断 输入管道 输出管道 判断管道
输入管道	0-num
输出管道	符合的素数
判断管道	判断退出的判断
*/
func isPrimes3(intChanPut chan int, primeChan chan int, exitChan chan bool) {

	var flag bool
label:
	for {
		select {
		case num := <-intChanPut:
			flag = true
			for j := 2; j < num; j++ {
				if num%j == 0 {
					flag = false
					continue
				}
			}
			if flag {
				primeChan <- num
				//fmt.Println("数字", num, "是素数。")
			}
		default:
			break label
		}
	}
	fmt.Println("协程已结束")
	exitChan <- true

}
